﻿using System;


//yes, I know this code of class can be reused, but for clear use I don't rewrite them into one method

namespace CalcConvertor
{
    class MathTool
    {
        private const int base2 = 2;
        private const int base8 = 8;
        private const int base10 = 10;
        private const int base16 = 16;
        private const string Hex10 = "A";
        private const string Hex11 = "B";
        private const string Hex12 = "C";
        private const string Hex13 = "D";
        private const string Hex14 = "E";
        private const string Hex15 = "F";

        private static string GetHexStrFromDec(string dec)
        {
            switch (dec)
            {

                case "10": return Hex10;
                case "11": return Hex11;
                case "12": return Hex12;
                case "13": return Hex13;
                case "14": return Hex14;
                case "15": return Hex15;
                default: return dec;
            }
        }
        private static string GetDecStrFromHex(string hex)
        {
            switch (hex)
            {
                case Hex10: return "10";
                case Hex11: return "11";
                case Hex12: return "12";
                case Hex13: return "13";
                case Hex14: return "14";
                case Hex15: return "15";
                default: return hex;
            }
        }

        public static string BinStrToDecStr(string binStr)
        {
            //1.1b=1*2^0+1*2^(-1)=1.5
            double value = 0;
            int index = 0;
            int dotIndex = binStr.IndexOf('.');
            if (dotIndex == -1) dotIndex = binStr.Length;
            foreach (char c in binStr)
            {
                if (c == '.') continue;
                int n = Int32.Parse(c.ToString());
                if (n != 0 && n != 1) return null;
                value +=  n* Math.Pow((double)base2, dotIndex - index - 1);
                index++;
            }

            return value.ToString();
        }
        public static string DecStrToOctStr(string decStr)
        {
            //divide to two parts
            string [] parts=new string [2]{null,null};
            if(decStr.IndexOf ('.')>-1)
            {
                parts[0] =decStr.Split ('.')[0];
                parts[1] =decStr.Split ('.')[1];
            }
            else
                parts[0] =decStr;

            string result=null;

            if (parts[0] != null)
            {
                long dividend = long.Parse(parts[0]);
                long divisor = (long)base8;
                long quotient = 0;
                long remainder = 0;
                do
                {
                    quotient = Math.DivRem(dividend, divisor, out remainder);
                    result = remainder.ToString() + result;
                    dividend = quotient;
                } while (quotient != 0);
            }

            if (parts[1] != null)
            {
                result += ".";

                double multiplier = Double.Parse("0." + parts[1]);
                double product = 0.0;
                long val=0;
                do
                {
                    product = multiplier * base8;
                    result += Convert.ToString((int)product);
                    multiplier = product-((int)product);
                } while (!Int64 .TryParse (product.ToString() ,out val));
                
            }
            return result;
        }
        public static string DecstrToHexStr(string decStr)
        {
            string[] parts = new string[2] { null, null };
            if (decStr.IndexOf('.') > -1)
            {
                parts[0] = decStr.Split('.')[0];
                parts[1] = decStr.Split('.')[1];
            }
            else
                parts[0] = decStr;

            string result = null;

            if (parts[0] != null)
            {
                long dividend = long.Parse(parts[0]);
                long divisor = (long)base16;
                long quotient = 0;
                long remainder = 0;
                do
                {
                    quotient = Math.DivRem(dividend, divisor, out remainder);
                    result = GetHexStrFromDec(remainder.ToString()) + result;
                    dividend = quotient;
                } while (quotient != 0);
            }

            if (parts[1] != null)
            {
                result += ".";

                double multiplier = Double.Parse("0." + parts[1]);
                double product = 0.0;
                long val = 0;
                do
                {
                    product = multiplier * base16;
                    result += GetHexStrFromDec(Convert.ToString((int)product));
                    multiplier = product - ((int)product);
                } while (!Int64.TryParse(product.ToString(), out val));

            }
            return result;
        }
        public static string OctStrToDecStr(string octStr)
        {
            double value = 0;
            int index = 0;
            int dotIndex = octStr.IndexOf('.');
            if (dotIndex == -1) dotIndex = octStr.Length;
            foreach (char c in octStr)
            {
                if (c == '.') continue;
                int n = Int32.Parse(c.ToString());
                if (n > 7) return null;
                value +=  n* Math.Pow((double)base8, dotIndex - index - 1);
                index++;
            }

            return value.ToString();
        }
        public static string DecStrToBinStr(string decStr)
        {
            string[] parts = new string[2] { null, null };
            if (decStr.IndexOf('.') > -1)
            {
                parts[0] = decStr.Split('.')[0];
                parts[1] = decStr.Split('.')[1];
            }
            else
                parts[0] = decStr;

            string result = null;

            if (parts[0] != null)
            {
                long dividend = long.Parse(parts[0]);
                long divisor = (long)base2;
                long quotient = 0;
                long remainder = 0;
                do
                {
                    quotient = Math.DivRem(dividend, divisor, out remainder);
                    result = remainder.ToString() + result;
                    dividend = quotient;
                } while (quotient != 0);
            }

            if (parts[1] != null)
            {
                result += ".";

                double multiplier = Double.Parse("0." + parts[1]);
                double product = 0.0;
                long val = 0;
                do
                {
                    product = multiplier * base2;
                    result += Convert.ToString((int)product);
                    multiplier = product - ((int)product);
                } while (!Int64.TryParse(product.ToString(), out val));

            }
            return result;
        }
        public static string HexStrToDecStr(string hexStr)
        {
            double value = 0;
            int index = 0;
            int dotIndex = hexStr.IndexOf('.');
            if (dotIndex == -1) dotIndex = hexStr.Length;
            foreach (char c in hexStr)
            {
                if (c == '.') continue;
                int n = Int32.Parse(GetDecStrFromHex(c.ToString()));
                if (n > 15) return null;
                value +=  n* Math.Pow((double)base16, dotIndex - index - 1);
                index++;
            }

            return value.ToString();
        }
    }
}
